package cn.bugstack.domain.strategy.service.armory;

import cn.bugstack.domain.strategy.model.entity.StrategyAwardEntity;
import cn.bugstack.domain.strategy.repositroy.IStrategyRepository;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.security.SecureRandom;
import java.util.*;

@Service
@Slf4j
public class StrategyArmory implements IStrategyArmory {

	@Resource
	private IStrategyRepository repositroy;

	@Override
	public boolean assembleLotteryStrategy(Long strategyId) {

		//查询策略配置
		List<StrategyAwardEntity> strategyAwardEntities =repositroy.queryStrategyAwardList(strategyId);
//		if(null == strategyAwardEntities || strategyAwardEntities.isEmpty()) return false;
		//获取最小值概率  拿到所有的awardRate进行比较，没有最小值时返回0
//		BigDecimal minAwardRate = strategyAwardEntities.stream()
//				.filter(Objects::nonNull)
//				.map(StrategyAwardEntity::getAwardRate)
//				.filter(Objects::nonNull)
//				.min(BigDecimal::compareTo)
//				.orElse(BigDecimal.ZERO);
		BigDecimal minAwardRate = strategyAwardEntities.stream()
				.map(StrategyAwardEntity :: getAwardRate)
				.min(BigDecimal::compareTo)
				.orElse(BigDecimal.ZERO);
		//3.获取概率值总和，Stream.reduce()是java8引入的流式操作聚合函数，可处理累加、最大值、最小值、拼接等逻辑
		BigDecimal totalRate = strategyAwardEntities.stream()
				.map(StrategyAwardEntity :: getAwardRate)
				.reduce(BigDecimal.ZERO,BigDecimal::add);
		// 获取总概率，安全处理 null
//		BigDecimal totalRate = strategyAwardEntities.stream()
//				.map(entity -> Optional.ofNullable(entity.getAwardRate()).orElse(BigDecimal.ZERO))
//				.reduce(BigDecimal.ZERO, BigDecimal::add);
		//4.用总概率%最小概率可获取概率范围，百分位、千分位、万分位
		//totalRate使用divide方法除以minAwardRate，指定精度为0，即取整，RoundingMode.CEILING表示向上取整
		BigDecimal rateRange = totalRate.divide(minAwardRate,0, RoundingMode.CEILING);
		ArrayList<Integer> strategyAwardSearchRateTables = new ArrayList<>(rateRange.intValue());
		/*5.遍历每一个奖品配置，根据其概率，在 strategyAwardSearchRateTables 列表中重
		复添加该奖品的 ID，使得后续可以通过随机数索引快速找到对应奖品。
		 */
		for(StrategyAwardEntity strategyAward : strategyAwardEntities){
			Integer awardId = strategyAward.getAwardId();
			BigDecimal awardRate = strategyAward.getAwardRate();
			//计算出每个概率值需要存放到查找表的数量并循环填充，multiply用于乘法运算，setScale保留0位小数并向上取整
			for (int i = 0; i < rateRange.multiply(awardRate).setScale(0, RoundingMode.CEILING).intValue() ;i++) {
				strategyAwardSearchRateTables.add(awardId);
			}
		}
		//6.将strategyAwardSearchRateTables乱序排序
		Collections.shuffle(strategyAwardSearchRateTables);
		//7.乱选排序后放入到map中
		HashMap<Integer,Integer> shuffleStrategyAwardSearchRateTables = new HashMap<>();
		for (int i = 0; i < strategyAwardSearchRateTables.size(); i++) {
			shuffleStrategyAwardSearchRateTables.put(i, strategyAwardSearchRateTables.get(i));
		}
		//8.存储到redis中
		repositroy.storeStrategyAwardSearchRateTables(String.valueOf(strategyId),shuffleStrategyAwardSearchRateTables.size(),shuffleStrategyAwardSearchRateTables);
		return true;
	}

	@Override
	public Integer getRandomAwardId(Long strategyId) {
		//根据策略id进行随机抽奖
		int rateRange = repositroy.getRateRange(strategyId);
		return repositroy.getStrategyAwardAssemble(String.valueOf(strategyId),new SecureRandom().nextInt(rateRange));
	}

}


